home *** CD-ROM | disk | FTP | other *** search
- # console.tcl --
- #
- # This code constructs the console window for an application. It
- # can be used by non-unix systems that do not have built-in support
- # for shells.
- #
- # SCCS: @(#) console.tcl 1.45 97/09/17 16:52:40
- #
- # Copyright (c) 1995-1997 Sun Microsystems, Inc.
- #
- # See the file "license.terms" for information on usage and redistribution
- # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- #
-
- # TODO: history - remember partially written command
-
- # tkConsoleInit --
- # This procedure constructs and configures the console windows.
- #
- # Arguments:
- # None.
-
- proc tkConsoleInit {} {
- global tcl_platform
-
- if {! [consoleinterp eval {set tcl_interactive}]} {
- wm withdraw .
- }
-
- if {"$tcl_platform(platform)" == "macintosh"} {
- set mod "Cmd"
- } else {
- set mod "Ctrl"
- }
-
- menu .menubar
- .menubar add cascade -label File -menu .menubar.file -underline 0
- .menubar add cascade -label Edit -menu .menubar.edit -underline 0
-
- menu .menubar.file -tearoff 0
- .menubar.file add command -label "Source..." -underline 0 \
- -command tkConsoleSource
- .menubar.file add command -label "Hide Console" -underline 0 \
- -command {wm withdraw .}
- if {"$tcl_platform(platform)" == "macintosh"} {
- .menubar.file add command -label "Quit" -command exit -accel Cmd-Q
- } else {
- .menubar.file add command -label "Exit" -underline 1 -command exit
- }
-
- menu .menubar.edit -tearoff 0
- .menubar.edit add command -label "Cut" -underline 2 \
- -command { event generate .console <<Cut>> } -accel "$mod+X"
- .menubar.edit add command -label "Copy" -underline 0 \
- -command { event generate .console <<Copy>> } -accel "$mod+C"
- .menubar.edit add command -label "Paste" -underline 1 \
- -command { event generate .console <<Paste>> } -accel "$mod+V"
-
- if {"$tcl_platform(platform)" == "windows"} {
- .menubar.edit add command -label "Delete" -underline 0 \
- -command { event generate .console <<Clear>> } -accel "Del"
-
- .menubar add cascade -label Help -menu .menubar.help -underline 0
- menu .menubar.help -tearoff 0
- .menubar.help add command -label "About..." -underline 0 \
- -command tkConsoleAbout
- } else {
- .menubar.edit add command -label "Clear" -underline 2 \
- -command { event generate .console <<Clear>> }
- }
-
- . conf -menu .menubar
-
- text .console -yscrollcommand ".sb set" -setgrid true
- scrollbar .sb -command ".console yview"
- pack .sb -side right -fill both
- pack .console -fill both -expand 1 -side left
- if {$tcl_platform(platform) == "macintosh"} {
- .console configure -font {Monaco 9 normal} -highlightthickness 0
- }
-
- tkConsoleBind .console
-
- .console tag configure stderr -foreground red
- .console tag configure stdin -foreground blue
-
- focus .console
-
- wm protocol . WM_DELETE_WINDOW { wm withdraw . }
- wm title . "Console"
- flush stdout
- .console mark set output [.console index "end - 1 char"]
- tkTextSetCursor .console end
- .console mark set promptEnd insert
- .console mark gravity promptEnd left
- }
-
- # tkConsoleSource --
- #
- # Prompts the user for a file to source in the main interpreter.
- #
- # Arguments:
- # None.
-
- proc tkConsoleSource {} {
- set filename [tk_getOpenFile -defaultextension .tcl -parent . \
- -title "Select a file to source" \
- -filetypes {{"Tcl Scripts" .tcl} {"All Files" *}}]
- if {"$filename" != ""} {
- set cmd [list source $filename]
- if [catch {consoleinterp eval $cmd} result] {
- tkConsoleOutput stderr "$result\n"
- }
- }
- }
-
- # tkConsoleInvoke --
- # Processes the command line input. If the command is complete it
- # is evaled in the main interpreter. Otherwise, the continuation
- # prompt is added and more input may be added.
- #
- # Arguments:
- # None.
-
- proc tkConsoleInvoke {args} {
- set ranges [.console tag ranges input]
- set cmd ""
- if {$ranges != ""} {
- set pos 0
- while {[lindex $ranges $pos] != ""} {
- set start [lindex $ranges $pos]
- set end [lindex $ranges [incr pos]]
- append cmd [.console get $start $end]
- incr pos
- }
- }
- if {$cmd == ""} {
- tkConsolePrompt
- } elseif [info complete $cmd] {
- .console mark set output end
- .console tag delete input
- set result [consoleinterp record $cmd]
- if {$result != ""} {
- .console insert insert "$result\n"
- }
- tkConsoleHistory reset
- tkConsolePrompt
- } else {
- tkConsolePrompt partial
- }
- .console yview -pickplace insert
- }
-
- # tkConsoleHistory --
- # This procedure implements command line history for the
- # console. In general is evals the history command in the
- # main interpreter to obtain the history. The global variable
- # histNum is used to store the current location in the history.
- #
- # Arguments:
- # cmd - Which action to take: prev, next, reset.
-
- set histNum 1
- proc tkConsoleHistory {cmd} {
- global histNum
-
- switch $cmd {
- prev {
- incr histNum -1
- if {$histNum == 0} {
- set cmd {history event [expr [history nextid] -1]}
- } else {
- set cmd "history event $histNum"
- }
- if {[catch {consoleinterp eval $cmd} cmd]} {
- incr histNum
- return
- }
- .console delete promptEnd end
- .console insert promptEnd $cmd {input stdin}
- }
- next {
- incr histNum
- if {$histNum == 0} {
- set cmd {history event [expr [history nextid] -1]}
- } elseif {$histNum > 0} {
- set cmd ""
- set histNum 1
- } else {
- set cmd "history event $histNum"
- }
- if {$cmd != ""} {
- catch {consoleinterp eval $cmd} cmd
- }
- .console delete promptEnd end
- .console insert promptEnd $cmd {input stdin}
- }
- reset {
- set histNum 1
- }
- }
- }
-
- # tkConsolePrompt --
- # This procedure draws the prompt. If tcl_prompt1 or tcl_prompt2
- # exists in the main interpreter it will be called to generate the
- # prompt. Otherwise, a hard coded default prompt is printed.
- #
- # Arguments:
- # partial - Flag to specify which prompt to print.
-
- proc tkConsolePrompt {{partial normal}} {
- if {$partial == "normal"} {
- set temp [.console index "end - 1 char"]
- .console mark set output end
- if [consoleinterp eval "info exists tcl_prompt1"] {
- consoleinterp eval "eval \[set tcl_prompt1\]"
- } else {
- puts -nonewline "% "
- }
- } else {
- set temp [.console index output]
- .console mark set output end
- if [consoleinterp eval "info exists tcl_prompt2"] {
- consoleinterp eval "eval \[set tcl_prompt2\]"
- } else {
- puts -nonewline "> "
- }
- }
- flush stdout
- .console mark set output $temp
- tkTextSetCursor .console end
- .console mark set promptEnd insert
- .console mark gravity promptEnd left
- }
-
- # tkConsoleBind --
- # This procedure first ensures that the default bindings for the Text
- # class have been defined. Then certain bindings are overridden for
- # the class.
- #
- # Arguments:
- # None.
-
- proc tkConsoleBind {win} {
- bindtags $win "$win Text . all"
-
- # Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
- # Otherwise, if a widget binding for one of these is defined, the
- # <KeyPress> class binding will also fire and insert the character,
- # which is wrong. Ditto for <Escape>.
-
- bind $win <Alt-KeyPress> {# nothing }
- bind $win <Meta-KeyPress> {# nothing}
- bind $win <Control-KeyPress> {# nothing}
- bind $win <Escape> {# nothing}
- bind $win <KP_Enter> {# nothing}
-
- bind $win <Tab> {
- tkConsoleInsert %W \t
- focus %W
- break
- }
- bind $win <Return> {
- %W mark set insert {end - 1c}
- tkConsoleInsert %W "\n"
- tkConsoleInvoke
- break
- }
- bind $win <Delete> {
- if {[%W tag nextrange sel 1.0 end] != ""} {
- %W tag remove sel sel.first promptEnd
- } else {
- if [%W compare insert < promptEnd] {
- break
- }
- }
- }
- bind $win <BackSpace> {
- if {[%W tag nextrange sel 1.0 end] != ""} {
- %W tag remove sel sel.first promptEnd
- } else {
- if [%W compare insert <= promptEnd] {
- break
- }
- }
- }
- foreach left {Control-a Home} {
- bind $win <$left> {
- if [%W compare insert < promptEnd] {
- tkTextSetCursor %W {insert linestart}
- } else {
- tkTextSetCursor %W promptEnd
- }
- break
- }
- }
- foreach right {Control-e End} {
- bind $win <$right> {
- tkTextSetCursor %W {insert lineend}
- break
- }
- }
- bind $win <Control-d> {
- if [%W compare insert < promptEnd] {
- break
- }
- }
- bind $win <Control-k> {
- if [%W compare insert < promptEnd] {
- %W mark set insert promptEnd
- }
- }
- bind $win <Control-t> {
- if [%W compare insert < promptEnd] {
- break
- }
- }
- bind $win <Meta-d> {
- if [%W compare insert < promptEnd] {
- break
- }
- }
- bind $win <Meta-BackSpace> {
- if [%W compare insert <= promptEnd] {
- break
- }
- }
- bind $win <Control-h> {
- if [%W compare insert <= promptEnd] {
- break
- }
- }
- foreach prev {Control-p Up} {
- bind $win <$prev> {
- tkConsoleHistory prev
- break
- }
- }
- foreach prev {Control-n Down} {
- bind $win <$prev> {
- tkConsoleHistory next
- break
- }
- }
- bind $win <Insert> {
- catch {tkConsoleInsert %W [selection get -displayof %W]}
- break
- }
- bind $win <KeyPress> {
- tkConsoleInsert %W %A
- break
- }
- foreach left {Control-b Left} {
- bind $win <$left> {
- if [%W compare insert == promptEnd] {
- break
- }
- tkTextSetCursor %W insert-1c
- break
- }
- }
- foreach right {Control-f Right} {
- bind $win <$right> {
- tkTextSetCursor %W insert+1c
- break
- }
- }
- bind $win <F9> {
- eval destroy [winfo child .]
- if {$tcl_platform(platform) == "macintosh"} {
- source -rsrc Console
- } else {
- source [file join $tk_library console.tcl]
- }
- }
- bind $win <<Cut>> {
- # Same as the copy event
- if {![catch {set data [%W get sel.first sel.last]}]} {
- clipboard clear -displayof %W
- clipboard append -displayof %W $data
- }
- break
- }
- bind $win <<Copy>> {
- if {![catch {set data [%W get sel.first sel.last]}]} {
- clipboard clear -displayof %W
- clipboard append -displayof %W $data
- }
- break
- }
- bind $win <<Paste>> {
- catch {
- set clip [selection get -displayof %W -selection CLIPBOARD]
- set list [split $clip \n\r]
- tkConsoleInsert %W [lindex $list 0]
- foreach x [lrange $list 1 end] {
- %W mark set insert {end - 1c}
- tkConsoleInsert %W "\n"
- tkConsoleInvoke
- tkConsoleInsert %W $x
- }
- }
- break
- }
- }
-
- # tkConsoleInsert --
- # Insert a string into a text at the point of the insertion cursor.
- # If there is a selection in the text, and it covers the point of the
- # insertion cursor, then delete the selection before inserting. Insertion
- # is restricted to the prompt area.
- #
- # Arguments:
- # w - The text window in which to insert the string
- # s - The string to insert (usually just a single character)
-
- proc tkConsoleInsert {w s} {
- if {$s == ""} {
- return
- }
- catch {
- if {[$w compare sel.first <= insert]
- && [$w compare sel.last >= insert]} {
- $w tag remove sel sel.first promptEnd
- $w delete sel.first sel.last
- }
- }
- if {[$w compare insert < promptEnd]} {
- $w mark set insert end
- }
- $w insert insert $s {input stdin}
- $w see insert
- }
-
- # tkConsoleOutput --
- #
- # This routine is called directly by ConsolePutsCmd to cause a string
- # to be displayed in the console.
- #
- # Arguments:
- # dest - The output tag to be used: either "stderr" or "stdout".
- # string - The string to be displayed.
-
- proc tkConsoleOutput {dest string} {
- .console insert output $string $dest
- .console see insert
- }
-
- # tkConsoleExit --
- #
- # This routine is called by ConsoleEventProc when the main window of
- # the application is destroyed. Don't call exit - that probably already
- # happened. Just delete our window.
- #
- # Arguments:
- # None.
-
- proc tkConsoleExit {} {
- destroy .
- }
-
- # tkConsoleAbout --
- #
- # This routine displays an About box to show Tcl/Tk version info.
- #
- # Arguments:
- # None.
-
- proc tkConsoleAbout {} {
- global tk_patchLevel
- tk_messageBox -type ok -message "Tcl for Windows
- Copyright \251 1996 Sun Microsystems, Inc.
-
- Tcl [info patchlevel]
- Tk $tk_patchLevel"
- }
-
- # now initialize the console
-
- tkConsoleInit
-